home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / utility2 / wclib.zip / WCLIB.DOC next >
Text File  |  1993-05-03  |  36KB  |  779 lines

  1. WCLIB.WCL (VERSION 1.0)                Copyright (c) 1993 Douglas Boling
  2. -------------------------------------------------------------------------
  3.                    First Published in PC Magazine May 25,1993 (Utilities)
  4. -------------------------------------------------------------------------
  5.  
  6. WCLIB.WCL:
  7.                Our WINCMD utility gave you a command language interpreter
  8. for Windows 3.1. WCLIB is a dynamic link library for the WINCMD utility.
  9. It enhances the WINCMD language by adding new functions that will let you
  10. move and size windows, read and write files, access the Windows Clipboard,
  11. and control your multimedia devices from a WINCMD program.
  12.  
  13. USING WCLIP
  14.  
  15.      To install WCLIB, you must copy WCLIB.WCL into the same directory as
  16. WINCMD.EXE.  When WINCMD is started it will automatically add all the new
  17. WCLIB functions to the WINCMD language.  You use the WCLIB functions exactly
  18. as you would the standard WINCMD functions:  Just enter the name of the
  19. function, followed by its parameters enclosed in parentheses.
  20.  
  21.      WCLIB's new functions can be divided into four functional groups:
  22. window management, file access, multimedia, and Clipboard.  A table
  23. listing them all is shown (below) in Figure 1.
  24.  
  25. WINDOW MANAGEMENT GROUP
  26.  
  27.      The function GetWindowHandle() returns the handle for a window on
  28. the screen.  In Windows programming jargon, a handle is a number that a
  29. program uses when referring to a window.  To get the handle of the
  30. Program Manager's main window, you would use the function 
  31.  
  32. proghand = GetWindowHandle("Program Manager")
  33.  
  34.      In WCLIB, knowing a window's handle is the key to controlling that
  35. window.  The standard functions included in WINCMD, such as AppActivate(),
  36. always refer to windows by their title bar text.  Unfortunately, not all
  37. windows have a title bar or other text.  The WCLIB functions that involve
  38. windows use the window handle instead and so can reference any window on
  39. the screen.
  40.  
  41.      The next two functions, SizeWindow() and MoveWindow(), let a WINCMD
  42. program set the size and position of windows on the screen.  SizeWindow()
  43. takes three parameters:  the handle of the window, the new width, and the
  44. new height.  The latter two parameters are specified in pixels.  For
  45. example, to resize the Program Manager window to a window 300 pixels wide
  46. by 200 high, you'd use the following lines:
  47.  
  48.                handle = GetWindowHandle("Program Manager")
  49.  
  50.                SizeWindow (handle, 200, 300)
  51.  
  52.  
  53. SizeWindow() returns TRUE (any nonzero value) if the function was
  54. successful and FALSE (a zero value) if it was not.
  55.  
  56.      The MoveWindow() function similarly takes three arguments:  the
  57. window handle, the horizonal position, and the vertical position.  To
  58. parallel the previous example, to move the Program Manager window to the
  59. top-left corner of the screen, the commands would be
  60.  
  61.                handle = GetWindowHandle("Program Manager")
  62.                MoveWindow (handle, 0, 0)
  63.  
  64.  
  65. As with the SizeWindow() function, MoveWindow() returns TRUE if the
  66. function was successful in moving the window and FALSE if it was not.
  67.  
  68.      While you often want to move and size a window, there are times
  69. when you simply wish to minimize or maximize it.  To minimize a window
  70. to an icon, you use the function MinimizeWindow(), whose only parameter
  71. is the handle of the window.  Similarly, MaximizeWindow() zooms a window
  72. to cover the entire desktop, and RestoreWindow() restores a window from
  73. an iconic or maximized state.  Both also take only the window handle as
  74. a parameter.  All three of these functions return TRUE if the function
  75. was successful and FALSE otherwise.
  76.  
  77.      Since being able to learn the specific position and size of a window
  78. is just as important as being able to move or size it yourself, WCLIB
  79. includes three functions that return information in this area.
  80. GetWindowSize() takes one parameter, the window handle, and it returns
  81. the size of the window.  Both the width and height of the window are
  82. encoded in the one returned parameter.  The width of the window is
  83. contained in the lower half of the returned value; the height is
  84. contained in the upper half.  To separate the two values, you can use
  85. the HighWord() and LowWord() functions.  For example, the following
  86. code fragment will display the size of the Program Manager's window:
  87.  
  88.            size = GetWindowSize (GetWindowHandle("Program Manager"))
  89.  
  90. Say "The Program Manager window is" HighWord(size) "high and" LowWord(size)
  91.       "wide"
  92.  
  93. As discussed in the last issue in connection with the WINCMD language,
  94. the SAY statement simply displays text in the WINCMD.EXE window.
  95.  
  96.      Notice in this example that instead of using a separate line to get
  97. and save the handle of the Program Manager window, I simply included the
  98. GetWindowHandle() function in the call to GetWindowSize().  While this is
  99. not necessary, some people find it convenient to write programs this way.
  100. It reduces the number of lines in the program and eliminates the need to
  101. create a variable to hold the window handle.  Note too that it might be
  102. good to check the GetWindowHandle() result before passing it on to
  103. GetWindowSize().
  104.  
  105.      The GetWindowPos() function is similar to GetWindowSize().  Its
  106. single parameter is the window handle, and it returns the position of
  107. that window encoded in the returned value.  Thus, by making only a few
  108. minor changes to the previous example, you can display the position of
  109. the Program Manager's window thus:
  110.  
  111.        pos = GetWindowPos (GetWindowHandle("Program Manager"))
  112.  
  113.    Say "The Program Manager window is at row" LowWord(pos) "and column"
  114.      HighWord(pos)
  115.  
  116.      GetWindowState() returns the state--iconic, restored, or
  117. maximized--of a window.  This function takes a window handle as its one
  118. parameter and returns a 1 if the window is in a restored state, a 2 if
  119. the window is being displayed as an icon, and a 3 if it is maximized.
  120.  
  121.      GetWindow() is a powerful function that can be used to track the
  122. relationships between a window and its parent, owner, or children.  The
  123. function takes two parameters:  the handle of the window, and a parameter
  124. that requests that a specified relationship will return a TRUE (nonzero)
  125. value.  Figure 2 (below) lists the relationships that can be requested
  126. and the value of the second parameter to request that relationship.
  127. GetWindow() returns the window handle for the window that has the
  128. specified relationship.  If no window meets the relationship requested,
  129. or if either parameter passed to GetWindow() is invalid, the function
  130. returns FALSE.
  131.  
  132.      Unfortunately, to explain these window relationships would take an
  133. entire article in itself.  For those who are interested in learning more
  134. about the subject, the best text is the classic Programming Windows, by
  135. PC Magazine contributing editor Charles Petzold.
  136.  
  137.      The GetWindowText() function is the inverse of GetWindowHandle().
  138. It returns the title text of a window from the window handle passed to
  139. it.  This function provides an easy way to convert a window handle
  140. returned by GetWindow() into a title that can be used by AppActivate()
  141. and the other functions of WINCMD that require title text.
  142.  
  143.      The next two functions, PostMessage() and SendMessage(), give a
  144. WINCMD program access to the very heart of Windows:  the message
  145. architecture.  Messages are the commands and notifications sent to
  146. windows by other windows and by Windows itself.  As with GetWindow(),
  147. a complete explanation of window messages is beyond the scope of this
  148. article, but the functions are included in the WCLIB repertoire to give
  149. WINCMD programs an additional level of functionality.
  150.  
  151.      Both PostMessage() and SendMessage() take four parameters: the
  152. handle of the window to which the message is to be sent, the message
  153. value, the word parameter for that message, and the long parameter.
  154. PostMessage() returns a zero if the function fails, and a nonzero
  155. otherwise.  SendMessage() returns the value returned by Windows'
  156. SendMessage() call.
  157.  
  158.      A handy use for PostMessage() is to tell an application to
  159. terminate by posting a WM_QUIT message to it.  For example, to tell
  160. the File Manager to terminate, you would use the following line:
  161.  
  162.          PostMessage (GetWindowHandle("File Manager"), 0x12, 0, 0)
  163.  
  164.      Windows has hundreds of different messages.  Again, the best source
  165. for learning about these messages is Charles Petzold's Programming
  166. Windows.  Since window messages are normally referred to by their names
  167. rather than by their actual number values, you will need to refer to
  168. the file WINDOWS.H, which is included with the Windows Software
  169. Development Kit and with other Windows development environments.  You
  170. must be very careful when using SendMessage() and PostMessage(), since
  171. sending the wrong message at the wrong time can be disastrous to the
  172. target window and even to Windows itself.
  173.  
  174.      The last two functions in the window management group are
  175. LoadIconFile() and SetIcon().  These are designed primarily to allow a
  176. WINCMD program to set the icon of its own window, but with care they
  177. can also be used to set the icons for other windows on the desktop.
  178. LoadIconFile() takes the filename of a Windows icon file as its only
  179. parameter.  If the file is successfully loaded, LoadIconFile() returns
  180. a handle to the icon.
  181.  
  182.      The two SetIcon() parameters are the handle of a window and the
  183. handle of the icon to use.  The function returns the handle of the icon
  184. that the window used previously.  For example, to set the icon of a
  185. WINCMD window with an icon from the file TRASH.ICO, the statements
  186. would be
  187.  
  188.          hicon = LoadIconFile ("TRASH.ICO")
  189.          if (hicon <> 0) holdicon = SetIcon (hmain, hicon)
  190.  
  191.  
  192.      In this example, the file TRASH.ICO is loaded and the variable  is
  193. set to the icon handle.  If the load fails, will be zero.  The IF
  194. statement allows the WINCMD window icon to be set only if the icon from
  195. TRASH.ICO was loaded successfully.  Note that this example is the first
  196. use of WINCMD's predefined variable, which is automatically set to the
  197. handle of the WIN-CMD window.  The only other predefined variable in
  198. the WINCMD language is, which is the instance handle for the current
  199. instance of WINCMD.EXE.
  200.  
  201. MULTIMEDIA FUNCTIONS
  202.  
  203.      Microsoft bundled its Multimedia Windows software with the standard
  204. Windows 3.1.  The multimedia interface itself is fairly complex:  It has
  205. over 100 APIs!  Fortunately, however, Microsoft also provided a high-level
  206. interface, called the Media Control Interface (MCI), which provides a
  207. much simpler way to communicate with multimedia devices.  Included in the
  208. MCI interface is a call that allows programs to use ASCII strings to
  209. command multimedia devices.  (Make sure you don't confuse these strings
  210. with those you may use to get your e-mail!)
  211.  
  212.      The WCLIB SendMCIString() function allows WINCMD programs to send
  213. MCI command strings to a multimedia device.  The single parameter to
  214. SendMCIString() is the command string to send.  If the command sent
  215. was successful, SendMCIString() returns any response the command returns.
  216. If the command fails, SendMCIString() returns the string ERROR, followed
  217. by the MCI error number that was returned.  For example, if you sent the
  218. command
  219.  
  220.           SENDMCISTRING ("open cdaudio")
  221.  
  222. a response of ERROR 291 would indicate that the CD-AUDIO device was
  223. already in use.
  224.  
  225.      The GetMCIErrorString() function lets a WINCMD program translate an
  226. error number returned by SendMCIString() into a string that describes the
  227. error.  The one parameter required is the error number returned by
  228. SendMCIString().  Note, however, that a WINCMD program must parse the
  229. error string returned by SendMCIString() in order to separate the error
  230. number from its preceding ERROR string.  For example, the following
  231. lines will display an error string if an MCI string command fails:
  232.  
  233. answer = SendMCIString (string)
  234.  
  235. if (Substr (answer,0 ,5) == "ERROR")
  236.  
  237.    say answer GetMCIErrorString (substr (answer, 6, 10))
  238.  
  239. else
  240.    say answer
  241.  
  242.  
  243. The MCIPLAY.WCM program shown later in this article further illustrates
  244. the use of these two multimedia functions.
  245.  
  246. FILE FUNCTIONS
  247.  
  248.      The WCLIB file functions allow you to read and write files.
  249. FileOpen() opens or creates a file for operation.  The function takes
  250. two parameters:  the name of the file to open and the access mode.
  251. The allowable access mode values are 0 for read-only, 1 for write-only,
  252. and 2 for read/write access.  FileOpen() returns a file handle that must
  253. be used for all other file functions.
  254.  
  255.      The FileMovePtr() function changes the position of the file
  256. read/write pointer; for example, the location in the file from which data
  257. will next be read or to which it will next be written.  The function takes
  258. three parameters:  the file handle, the pointer offset value, and a flag
  259. that indicates the method to be used when changing the pointer.  The
  260. method flag can be set to one of three values.  A 0 indicates that the
  261. file pointer should be moved to the specified offset from the start of
  262. the file.  A method flag setting of 1 indicates that the offset should
  263. be made from the current file pointer position, and a 2 indicates that
  264. the pointer should be offset from the end of the file.
  265.  
  266.      FileMovePtr() returns the new value of the file pointer for the
  267. file. For example, to set the file pointer to 100 bytes from the start
  268. of a file, the command would be
  269.  
  270.                                  FileMovePtr (hFile, 100, 0)
  271.  
  272.  
  273. To move the file pointer ahead 300 bytes, you would use the command
  274.  
  275.                                  FileMovePtr (hFile, 300, 1)
  276.  
  277.  
  278. Similarly, to set the file pointer to 200 bytes from the end of a file use
  279.  
  280.                                  FileMovePtr (hFile, -200, 2)
  281.  
  282.  
  283.      A common use for this last method of flag setting is to find the
  284. size of a file.  If you move the file pointer to an offset of 0 from the
  285. end of the file, the returned value will be the file size.  These examples
  286. all assume that the file has been previously opened and that the file
  287. handle has been assigned to the variable hFile.
  288.  
  289.      The FileRead() function reads bytes from a file and takes as its
  290. two parameters the file handle and the number of bytes to be read.
  291. The return value for the function is the actual data read, which can be
  292. assigned to a WINCMD variable by using the equal sign (=), as explained
  293. in the last issue.  The read is performed from the current position of
  294. the file pointer.  After the read is done, the file pointer is updated
  295. to point to the byte following the last byte read. If there are no more
  296. bytes in the file to read--if the file pointer is pointing to the end
  297. of the file--FileRead() returns -1.
  298.  
  299.      FileWrite() does the complementary job of writing to a file.  It
  300. also takes two parameters, the handle of the file, and a variable that
  301. contains the data to be written.  FileWrite() returns the number of
  302. bytes written to the file. If the file handle is invalid or if the file
  303. is read-only, FileWrite() returns 0.
  304.  
  305.      The FileClose() function closes a file and takes as its only
  306. parameter the handle to that file.  WINCMD programs should always close
  307. any files that have been opened before the program terminates.
  308.  
  309.      Finally, the FileExist() function determines whether a specified
  310. file exists. The function takes the name of the file as its one parameter
  311. and returns TRUE if the file exists, FALSE otherwise.  Note that the
  312. filename passed to FileExist() can contain wildcards.
  313.  
  314. CLIPBOARD FUNCTIONS
  315.  
  316.      The final two functions allow WINCMD programs to read and write text
  317. to the Windows Clipboard. GetClipText() takes no arguments and simply
  318. returns any text data in the Clipboard.  If the Clipboard is empty or if
  319. the data there cannot be rendered in a text format (if it contains a
  320. bitmap, for example,) GetClipText() returns 0.  SetClipText() empties
  321. the Clipboard and then sets it to whatever text has been passed to the
  322. function.  The function takes one argument:  the text to be placed in
  323. the Clipboard.
  324.  
  325. WCLIB AT WORK
  326.  
  327.      The WINCMD program, WORDFIX.WCM, shown (below) in Figure 3, demonstrates
  328. some of the new functions of WCLIB in the process of solving two of my
  329. major problems with Word for Windows.  One of these is that Word does
  330. not remember its size and location on the screen between launches.
  331. The other is that the application displays a message box demanding SHARE
  332. if a second copy is launched.  WORDFIX fixes the message box problem by
  333. first checking to see if Word is already running and, if so, switching
  334. the original Word window to the foreground.  If Word is not running,
  335. WORDFIX starts the program and then moves and resizes its window.
  336.  
  337.      The WORDFIX subroutine CheckRunning checks the title text of every
  338. window on the desktop to see whether a Word window is currently open on
  339. the screen.  This check consists of using GetWindow() to return the first
  340. window in the window manager list.  (The window manager is the part of
  341. Windows that manages the windows on the desktop.)  The routine then gets
  342. the title text for that window and compares it to the target window
  343. text--in this case, the string ``Microsoft Word''.  If the text matches,
  344. CheckRunning returns the handle of the window.  Otherwise, GetWindow is
  345. called again to get the next window in the window manager list and loops
  346. back.  The loop ends after the last window has been checked.
  347.  
  348.      The value returned by CheckRunning is compared with 0 to see whether
  349. Word is running.  If so, AppActivate() is called to bring Word to the
  350. foreground.  Since CheckRunning returns a window handle and AppActivate()
  351. needs the title text of a window, GetWindowText() is used to convert
  352. the handle into the necessary title bar text.
  353.  
  354.      Note that the CheckRunning subroutine provides a way around the
  355. GetWindowHandle() limitation I mentioned toward the beginning of this
  356. article, namely, that the function will fail if a window adds text on
  357. its title line beyond what you have specified.
  358.  
  359.      If Word is not running, WORDFIX launches it and waits half a second
  360. to allow Word to display its main window.  CheckRunning is called again
  361. to return the handle to the Word window.  If for some reason Word did
  362. not start, WORDFIX simply terminates.  Otherwise, MoveWindow() and
  363. SizeWidow() are called to place the Word window exactly where you want
  364. it on your screen.  WORDFIX quietly terminates when it has completed
  365. its business.
  366.  
  367.      One endearing feature of WINCMD programs is that they can be
  368. hidden behind any icon in the Program Manager.  I have WORDFIX in my
  369. Programs group with the Word for Windows icon set instead of the
  370. default WINCMD icon. This way it looks as if I am simply starting Word,
  371. when in fact I'm using a WINCMD program to start the application.
  372.  
  373.      The MCIPLAY.WCM program, which is shown (below) in Figure 4, uses the MCI
  374. string interface to let you control multimedia devices on your system.
  375. The program is rather straightforward.  It consists of the MCI string
  376. functions discussed earlier, the AskBox() function which is used to query
  377. the user for the MCI command, and a WHILE loop that continues the process
  378. until the user has pressed the CANCEL button on the dialog box.  The SAY
  379. statement is used to display any return messages from the MCI.
  380.  
  381.      If you have the file GONG.WAV in your Windows directory, you can
  382. hear MCIPLAY in operation by entering
  383.  
  384.                                      open waveaudio
  385.                                      play waveaudio!\windows\gong.wav
  386.                                      close waveaudio
  387.  
  388.  
  389. HOW WINCMD AND WCLIB WORK
  390.  
  391.       Space limitations in the earlier issue precluded a technical
  392. discussion of the WINCMD interpreter, so I'll review that program
  393. before considering WCLIB.  The operation of the WINCMD interpreter
  394. centers around its variable list.  This list contains all the keywords
  395. of the WINCMD language--IF, WHILE, DO, and so on--plus all the words
  396. that have been tokenized from the ASCII file that the interpreter is
  397. currently executing as a WINCMD program.
  398.  
  399.      The process of running a WINCMD program can be divided into three
  400. steps:  resetting the interpreter, loading and tokenizing the WINCMD
  401. program, and interpreting the program's token list.  The first step
  402. involves loading the variable list with the WINCMD language keywords.
  403. Keywords are loaded into the list together with pointers to the routines
  404. in WINCMD.EXE that will actually execute the keywords' functions.  Thus
  405. the IF keyword is loaded with a pointer to the LocalIF routine in
  406. WINCMD.EXE, for example.  The command line parameters are then loaded
  407. into the variable list so that they will be accessible to the program.
  408. At this point, any function libraries with a .WCL extension are called
  409. to load their functions into the variable list as well.  (I'll discuss
  410. what happens when a .WCL library is loaded shortly.)
  411.  
  412.      Once the variable list has been initialized, the WINCMD program to
  413. be executed is read into a block of global memory.  The file is then
  414. scanned, a word at a time, with the first character of each word
  415. determining how the WINCMD tokenizer treats the word.
  416.  
  417.       If the word begins with a letter or an underscore, it is treated
  418. as a variable name.  WINCMD.EXE then searches the variable list to see
  419. whether the word is already there.  If it's not, the word is added to
  420. the variable list and a pointer for the entry is added to another list,
  421. called the line token list.  (This list consists mainly of pointers to
  422. tokens in the variable list.)  The order of the pointers in the token
  423. list is the same as the order of the words in the WINCMD program.
  424.  
  425.      At this point the interpreter is converting the ASCII words in the
  426. WINCMD program into pointers to variables and keywords in the variable
  427. list.  Thus when WINCMD is subsequently executed, the interpreter only
  428. has to work with the pointers and does not need to retokenize each line
  429. as it is executed.
  430.  
  431.       There can be other items in the line token list besides pointers
  432. to entries in the variable list.  If the word being parsed does not begin
  433. with a letter or an underscore but with a number, the interpreter converts
  434. the word into a 32-bit number that is added to the token list as a numeric
  435. constant.  If the tokenizer sees a double quote character, it assumes that
  436. anything up to the next quote is a string constant.  Instead of adding
  437. the quoted string to the variable list, the tokenizer adds it to the line
  438. token list as a string constant.
  439.  
  440.      To summarize the tokenization process, let's look at the simple,
  441. three-line WINCMD program listed below.
  442.  
  443. FRED = 5
  444. IF (BOB < 5)
  445.  BOB = FRED + 3
  446.  
  447.  
  448.      This program begins as an ASCII file. After the file has been parsed,
  449. the variable list contains all the keywords plus two variable names, FRED
  450. and BOB: 
  451.  
  452. While
  453. Do
  454. If
  455. =
  456. >
  457. <
  458. +
  459. -
  460. .
  461. .
  462. .
  463. BOB
  464. FRED
  465.  
  466.  
  467. The original values assigned to the variables are the names of the
  468. variables, that is, FRED is assigned the string ``FRED'' and BOB is
  469. assigned the string ``BOB''. As shown (below) in Figure 5, the token list
  470. contains such items as line-number tokens, variable-pointer tokens, and
  471. numeric-constant tokens. Note that the items in the line token list are
  472. in the same order as the words from the original file.
  473.  
  474.      Once a WINCMD program has been tokenized, the only remaining task
  475. is to execute it, starting with the first item in the line token list.
  476. If the item is a pointer to a variable, the second item is checked to
  477. see if it is an equal sign.  If so, the items beyond the equal sign are
  478. evaluated, and the result is assigned to the variable at the start of
  479. the line.
  480.  
  481.      In the example shown in Figure 5, the first line starts with the
  482. variable FRED, so the interpreter checks to see if the second item is
  483. an equal sign.  Since it is, the interpreter evaluates the rest of the
  484. items on that line and assigns the result (in this case 5) to the
  485. variable FRED.  After the first line of the program has been executed,
  486. the entry in the variable list for FRED also contains the value 5.
  487. Since nothing has been assigned to the variable BOB, the data for that
  488. entry simply contains the string ``BOB''. 
  489.  
  490.      The first item in the line token list for the second line is a
  491. keyword, so the interpreter calls the routine pointed to by the IF
  492. entry in the variable list. The IF routine then evaluates the items
  493. in the line token list that make up the condition on the line following
  494. the IF.  Depending on the result of the evaluation, this line may or may
  495. not be executed.  In the Figure 5 example, the variable BOB is still
  496. assigned the string ``BOB'', so its numeric value is 0.  Since 0 is
  497. less than 5, the line following the IF statement is executed.
  498.  
  499.      The third line of this program, like the first, is a simple
  500. assignment statement. The items beyond the equal sign are evaluated
  501. and in this case FRED is 5, so the result is 5 + 3 or 8.  When the
  502. interpreter tries to execute the line after the last assignment, it
  503. sees the end-of-file token, meaning the program has finished.
  504.  
  505.      Calling a predefined function is similar to processing a keyword.
  506. Function names are listed in the variable list, along with the keywords
  507. and variables.  As with keywords, predefined functions each have a
  508. pointer in the variable list that points to the WINCMD.EXE subroutine
  509. that executes the function.  Thus, executing a function is simply a
  510. matter of parsing its parameters and calling the routine that executes
  511. it.
  512.  
  513. ADDING LIBRARY FUNCTIONS
  514.  
  515.      Since functions are simply items in the variable list, it's fairly
  516. easy for libraries such as WCLIB to add functions. They are simply added
  517. to the variable list. When WINCMD.EXE is launched, it looks for files
  518. with a .WCL  extension in its directory, and if any are found,
  519. LoadLibrary is called to load the file as a DLL.  If the load is
  520. successful and the .WCL DLL has external entry points named WCLibLoad
  521. and WCLibFunc, it is assumed to be a WINCMD function library.  The DLL
  522. WCLibLoad routine is called immediately so the library can perform any
  523. initialization processing necessary, and the WCLibFunc entry point is
  524. saved in WINCMD.EXE.  Later, when a function from the library is called,
  525. the WCLibEntry point is called to execute the function.
  526.  
  527.      When the interpreter is reset, a third entry point, WCLibReset, is
  528. called.  The library then uses a callback function in WINCMD.EXE to add
  529. entries to the WINCMD variable list.  These entries include the name of
  530. the function and numbers that indicate the source DLL of the function
  531. and a function number.  The interpreter uses these numbers to determine
  532. which DLL to call when the function is called in a WINCMD program.
  533.  
  534.      When the WCLibFunc routine in WCLIB is called, it uses the function
  535. number passed with the call to look up a pointer for the proper function
  536. to call inside the DLL.  The WCLibFunc call also includes a pointer to a
  537. callback entry point in WINCMD.EXE.  This allows libaries such as WCLIB
  538. to call routines that manipulate entries in the variable list.  The
  539. callback is necessary because multiple instances of WINCMD.EXE may be
  540. running at any one time.  The callback allows the single instance of the
  541. WCLIB DLL to operate on the correct variable list each time it is called.
  542.  
  543.      Fortunately, the user need not appreciate the complex interaction
  544. between WINCMD.EXE and WCLIB.  Together they provide a powerful command
  545. language that can be used to control your Windows desktop.  And the fact
  546. that WINCMD can be extended with additional libraries makes its language
  547. an ever-evolving process. Who knows? There may be another WINCMD function
  548. library  sometime in the future!
  549. -------------------------------------------------------------------------
  550. DOUGLAS BOLING IS A CONTRIBUTING EDITOR TO PC MAGAZINE.
  551. -------------------------------------------------------------------------
  552.  
  553.                          The New WCLIB Functions
  554.  
  555. Window Management Functions            Action
  556. --------------------------------------------------------------------------
  557.  
  558. GetWindowHandle (title text)             Returns the handle of the window with
  559.                                            the matching title text
  560. SizeWindow (window handle, cx, cy)       Resizes a window
  561.  
  562. MoveWindow (window handle, x, y)         Moves a window
  563.  
  564. MinimizeWindow (window handle)           Minimizes a window
  565.  
  566. MaximizeWindow (window handle)           Maximizes a window
  567.  
  568. RestoreWindow (window handle)            Restores a window
  569.  
  570. GetWindowSize (window handle)            Returns the size of a window
  571.  
  572. HighWord (number)                        Returns the upper 16 bits of a number
  573.  
  574. LowWord (number)                         Returns the lower 16 bits of a number
  575.  
  576. GetWindowPos (window handle)             Returns the x and y coordinates for
  577.                                            a window
  578.  
  579. GetWindowState (window handle)           Returns the state
  580.                                          (icon/restored/zoomed) of a window
  581.  
  582. GetWindow (window handle, relation)      Returns the handle of a window
  583.                                            related to a window
  584.  
  585. GetWindowText (window handle)            Returns the title text for a window
  586.  
  587. PostMessage (window handle, message
  588. number, word param, long param)          Posts a message to a window
  589.  
  590. SendMessage (window handle, message
  591. number, word param, long param)          Sends a message to a window
  592.  
  593. LoadIconFile (icon filename)             Loads an icon and returns an icon
  594.                                            handle
  595.  
  596. SetIcon (window handle, icon handle)     Sets a window's icon
  597. --------------------------------------------------------------------------
  598.  
  599. Multimedia Functions                     Action
  600. --------------------------------------------------------------------------
  601.  
  602. SendMCIString (MCI string)               Sends an MCI command string
  603.  
  604. GetMCIErrorString (MCI error number)     Returns an error message for an
  605.                                            MCI error number
  606. --------------------------------------------------------------------------
  607. File Functions                           Action
  608. --------------------------------------------------------------------------
  609.  
  610. FileOpen (filename, access mode)         Opens a file
  611.  
  612. FileMovePtr (file handle, offset, flag)  Moves a file read/write pointer
  613.  
  614. FileRead (file handle, bytes to read)    Reads bytes from a file
  615.  
  616. FileWrite (file handle, data to write)   Writes data to a file
  617.  
  618. FileClose (file handle)                  Closes a file
  619.  
  620. FileExist (filename)                     Determines whether a file exists
  621. --------------------------------------------------------------------------
  622. Clipboard Functions                      Action
  623. --------------------------------------------------------------------------
  624.  
  625. GetClipText ()                           Retrieves text from the Clipboard
  626.  
  627. SetClipText (data for Clipboard)         Sets the Clipboard contents
  628. ---------------------------------------------------------------------------
  629. Figure 1:  By adding the new functions provided by WCLIB.WCL, you can write
  630. far more powerful programs in the WINCMD command language.  The functions are
  631. listed in the order they appear in the text.
  632. ==============================================================================
  633.  
  634. GETWINDOW() Relationships
  635. ------------------------------------------------------------------------------
  636. Value       Meaning
  637. -----------------------------------------------
  638. 0           First sibling for a child window
  639. 1           Last sibling for a child window
  640. 2           Next sibling for a child window
  641. 3           Previous sibling for a child window
  642. 4           The owner of the window
  643. 5           The first child window of a window
  644. 6           The parent of a window
  645. -----------------------------------------------------------------------------
  646. Figure 2:  The second parameter to GetWindow() must specify one of these allowed values.
  647. =============================================================================
  648.  
  649.                           WORDFIX.WCM
  650.                         Complete Listing
  651. //============================================================
  652. // WinCmd program to fix problems with WinWord
  653. //
  654. // Copyright (c) 1993 Douglas Boling
  655. //============================================================
  656. //
  657. // Check to see if Word already running.  If so,
  658. // just switch to Word Window and exit
  659. //
  660. handle = checkrunning ("Microsoft Word")
  661. if (handle) do
  662.    appactivate (getwindowtext (handle))
  663.    exit
  664. end
  665.  
  666. //
  667. // Launch Word and wait .5 seconds
  668. //
  669. "\winword.exe"
  670.  
  671. delay (500)
  672.  
  673. //
  674. // Attempt to get handle to Word's main window.  If 
  675. // we can't quit.
  676. //
  677. handle = CheckRunning ("Microsoft Word")
  678. if (handle == 0) 
  679.    exit
  680.  
  681. // 
  682. // Move and size window to my specs
  683. //
  684. MoveWindow (handle, 200, 15)
  685. SizeWindow (handle, 900, 950)
  686. exit
  687.  
  688. //------------------------------------------------------------
  689. // CheckRunning - A routine that scans all windows to see
  690. // if a window has a partial matching title text
  691. //------------------------------------------------------------
  692. checkrunning:
  693. //
  694. // Get first window in window list
  695. //
  696. handle = getwindow (hmain, 0)
  697. //
  698. // Loop until no more windows
  699. // 
  700. while (handle <> 0) do
  701.    //
  702.    // Get window text
  703.    //
  704.    text = getwindowtext (handle) 
  705.    //
  706.    // If the first part of the window text matches the
  707.    // argument passed to CheckRunning return handle
  708.    //
  709.    if (substr (text, 0, length(arg(1))) == arg(1))
  710.       return handle
  711.    //
  712.    // Get next window handle in window list
  713.    //
  714.    handle = getwindow (handle, 2)
  715. end
  716. //
  717. // No matching window found, return 0
  718. //
  719. return 0
  720. ----------------------------------------------------------------------------
  721. Figure 3:  The WINCMD WORDFIX program manages the way Word for Windows
  722. starts.
  723. ----------------------------------------------------------------------------
  724.                                MCIPLAY.WCM
  725.                              Complete Listing
  726. //==============================================================
  727. // MCIPLAY - A WinCmd program that sends command strings using
  728. // the SendMCIString function
  729. // Copyright (c) 1993 Douglas Boling
  730. //==============================================================
  731. //
  732. // Ask the user for an MCI string command
  733. //
  734. string = AskBox ("Enter MCI String", " ")
  735. // 
  736. // See if the user pressed the cancel button
  737. //
  738. if (a+string == a)
  739.    string = EXIT
  740. //
  741. // Loop until cancel pressed
  742. //
  743. while (string <> exit) do
  744.    //
  745.    // Send the MCI string
  746.    //
  747.    answer = SendMCIString (string)
  748.    //
  749.    // Check for errors.  If error, print error string
  750.    //
  751.    if (substr (answer,0 ,5) == "ERROR")
  752.       say answer getmcierrorstring (substr (answer, 6, 10))
  753.    else
  754.       say answer 
  755.    //
  756.    // Get next command
  757.    //
  758.    string = AskBox ("Enter MCI String", string)
  759.    if (a+string == a)
  760.       string = EXIT
  761. end
  762. exit
  763. --------------------------------------------------------------------------
  764. Figure 4:  MCIPLAY is a WINCMD program for controlling multimedia devices.
  765. ==========================================================================
  766.  
  767. ==============================================================================
  768.  
  769.                            Line Token List
  770. ------------------------------------------------------
  771. LINE 0  | VAR (FRED)    |  OPERATOR (=)|CONSTANT (5)|
  772. -----------------------------------------------------------------
  773. LINE 1  | STATEMENT (IF)|  VAR (BOB)   |OPERATOR (<)|CONSTANT (5)|
  774. -----------------------------------------------------------------------------
  775. LINE 2  | VAR (BOB)     |  OPERATOR (=)|VAR (FRED)  |OPERATOR (+)|CONSTANT(3)|
  776. -----------------------------------------------------------------------------
  777.  
  778. Figure 5:  The WINCMD interpreter uses a list of pointers like this one to execute its programs.
  779. =============================================================================